using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Pavilion.Control
{
    public class DropDownList : Control
    {
        private DropDownMenu dropDownMenu;
        private Label label;
        private TextBox textBox;
        private Button dropButton;
        private DropDownItem selectedItem;

        public event Action<DropDownItem> ItemSelected;

        public DropDownList(Rectangle bounds) : base()
        {
            Initialization(bounds);
        }

        public DropDownList(Rectangle bounds, DropDownItem[] dropDownItems) : base()
        {
            Initialization(bounds);
            AddRange(dropDownItems);
        }

        private void Initialization(Rectangle bounds)
        {
            AreaBounds = bounds;
            DisplayDownwards = true;

            textBox = new TextBox(new Rectangle(0, 0, AreaBounds.Width - AreaBounds.Height, AreaBounds.Height));
            textBox.TextChanged += new Action<string>(TextBox_TextChanged);
            label = new Label("", new Rectangle(0, 0, AreaBounds.Width - AreaBounds.Height, AreaBounds.Height), Color.White);

            textBox.TextAllign = label.TextAllign = Allign.Left;
            textBox.TextSize = label.TextSize = 0.3f;
            textBox.TextColor = label.TextColor = Color.Black;

            dropButton = new Button("+", new Rectangle(AreaBounds.Width - AreaBounds.Height, 0, AreaBounds.Height, AreaBounds.Height), 0.5f);
            dropButton.Pressed += new Action(dropButton_Pressed);

            dropDownMenu = new DropDownMenu();
            dropDownMenu.Visible = false;
            dropDownMenu.Position = new Point(0, AreaBounds.Height);
            dropDownMenu.Width = bounds.Width;

            this._Collection.Add(label);
            this._Collection.Add(dropButton);
        }

        /// <summary>
        /// Adds a DropDownItem to this control.
        /// </summary>
        public void AddItem(DropDownItem item)
        {
            dropDownMenu.AddItem(item);
            item.ItemPressed += new Action<DropDownItem>(Item_ItemPressed);
        }

        /// <summary>
        /// Adds a range of items to this menu.
        /// </summary>
        /// <param name="dropDownItems"></param>
        public void AddRange(DropDownItem[] dropDownItems)
        {
            for (int i = 0; i < dropDownItems.Length; i++)
                AddItem(dropDownItems[i]);
        }

        /// <summary>
        /// Removes the list of items in this menu.
        /// </summary>
        public void Clear()
        {
            for (int i = 0; i < dropDownMenu.Count; i++)
                dropDownMenu[i].ItemPressed -= new Action<DropDownItem>(Item_ItemPressed);
            dropDownMenu.Clear();
        }

        /// <summary>
        /// Removes the item form the list.
        /// </summary>
        /// <param name="item">The item to be removed.</param>
        public bool Remove(DropDownItem item)
        {
            if (dropDownMenu.Remove(item))
            {
                item.ItemPressed -= new Action<DropDownItem>(Item_ItemPressed);
                return true;
            }

            return false;
        }

        private void ChangeText(string text)
        {
            label.Text = text;
            textBox.Text = text;
        }

        public bool IsWritable
        {
            get { return this._Collection.Contains(textBox); }
            set
            {
                if (IsWritable == value)
                    return;

                if (value)
                {
                    this._Collection.Remove(label);
                    this._Collection.Add(textBox);
                }
                else
                {
                    this._Collection.Remove(textBox);
                    this._Collection.Add(label);
                }
            }
        }

        /// <summary>
        /// Gets the amount of items that are in this DropDownList.
        /// </summary>
        public int Count
        {
            get { return dropDownMenu.Count; }
        }

        /// <summary>
        /// Gets or sets the value at the given index.
        /// </summary>
        /// <param name="index">The index of the item within this list.</param>
        public DropDownItem this[int index]
        {
            get { return dropDownMenu[index]; }
            set
            {
                Remove(dropDownMenu[index]);
                AddItem(value);
            }
        }

        /// <summary>
        /// Gets or sets the selected item of this list.
        /// </summary>
        public DropDownItem SelectedItem
        {
            get { return selectedItem; }
            set
            {
                for (int i = 0; i < Count; i++)
                {
                    if (value == dropDownMenu[i])
                    {
                        ChangeText(value.Text);
                        selectedItem = value;
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets whether the DropDownList will be facing upwards or downwards.
        /// </summary>
        public bool DisplayDownwards { get; set; }

        private void dropButton_Pressed()
        {
            int yPos;

            if (DisplayDownwards)
                yPos = ScreenBounds.Y + AreaBounds.Height;
            else
                yPos = ScreenBounds.Y - dropDownMenu.AreaBounds.Height; 

            dropDownMenu.Show(new Point(ScreenBounds.X, yPos));
        }

        private void Item_ItemPressed(DropDownItem item)
        {
            ChangeText(item.Text);
            selectedItem = item;

            if (ItemSelected != null)
                ItemSelected(selectedItem);
        }

        private void TextBox_TextChanged(string text)
        {
            if (SelectedItem != null)
            {
                SelectedItem.Text = text;
            }
        }
    }
}
